package cn.bugstack.middleware.db.router.config;

import cn.bugstack.middleware.db.router.DBRouterConfig;
import cn.bugstack.middleware.db.router.dynamic.DynamicDataSource;
import cn.bugstack.middleware.db.router.exception.AppException;
import cn.bugstack.middleware.db.router.util.Contants;
import cn.bugstack.middleware.db.router.util.PropertyUtil;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 这是 自动装配的入口
 *
 * @author lihh
 */
@Configuration
public class DataSourceAutoConfig implements EnvironmentAware {
  
  // 这是 配置的数据源
  private final Map<String, Map<String, Object>> dataSourceMap = new HashMap<>();
  
  // 分库个数
  private int dbCount;
  // 分表个数
  private int tbCount;
  
  @Bean
  public DBRouterConfig dbRouterConfig() {
    return new DBRouterConfig(dbCount, tbCount);
  }
  
  /**
   * 通过这个方法中 设置数据源
   *
   * @return 返回的数据源
   * @author lihh
   */
  @Bean
  public DataSource dataSource() {
    // 创建数据源
    Map<Object, Object> targetDataSources = new HashMap<>();
    for (String dbInfo : dataSourceMap.keySet()) {
      Map<String, Object> objMap = dataSourceMap.get(dbInfo);
      // DriverManagerDataSource 驱动管理数据源
      targetDataSources.put(dbInfo, new DriverManagerDataSource(
          objMap.get("url").toString(),
          objMap.get("username").toString(),
          objMap.get("password").toString())
      );
    }
    // 设置数据源
    DynamicDataSource dynamicDataSource = new DynamicDataSource();
    // 从这里配置了 所有的数据源
    dynamicDataSource.setTargetDataSources(targetDataSources);
    return dynamicDataSource;
  }
  
  /**
   * 通过该 重写方法中 设置方法
   *
   * @param environment 环境变量
   * @author lihh
   */
  @SuppressWarnings("DataFlowIssue")
  @Override
  public void setEnvironment(Environment environment) {
    String prefix = "router.jdbc.datasource.";
    
    String dbCountPath = prefix + "dbCount",
        tbCountPath = prefix + "tbCount",
        listPath = prefix + "list";
    if (null == environment.getProperty(dbCountPath)) {
      throw new AppException(String.format(Contants.DB_AND_TABLE_COUNT_PARAMS_MSG, dbCountPath));
    }
    if (null == environment.getProperty(tbCountPath)) {
      throw new AppException(String.format(Contants.DB_AND_TABLE_COUNT_PARAMS_MSG, tbCountPath));
    }
    if (null == environment.getProperty(listPath)) {
      throw new AppException(String.format(Contants.DB_AND_TABLE_COUNT_PARAMS_MSG, listPath));
    }
    
    // 这里 从环境中获取值
    dbCount = Integer.parseInt(environment.getProperty(dbCountPath));
    tbCount = Integer.parseInt(environment.getProperty(tbCountPath));
    String dataSources = environment.getProperty(listPath);
    
    // dbInfo 从这里配置数据源信息 alias
    for (String dbInfo : dataSources.split(",")) {
      Map<String, Object> dataSourceProps = PropertyUtil.handle(environment, prefix + dbInfo, Map.class);
      // 这个 dbInfo 是 db01, db02 等标识
      dataSourceMap.put(dbInfo, dataSourceProps);
    }
  }
  
}
